<?php
//  +----------------------------------------------------------------------
//  | Copyright (c) 2015-2025 http://www.hdphp.cn All rights reserved.
//  | Licensed ( http://www.hdphp.cn/licenses/ )
//  | Author: Jack <sophia2152@qq.com>
//  | 官方网址: http://www.hdphp.cn
//  | 这不是一个自由软件！您只能在不用于商业目的的前提下对程序代码进行修改和使用。
//  | 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
//  +----------------------------------------------------------------------
namespace hdphp\utils;

use Firebase\JWT\Key;
use hdphp\exceptions\AdminException;
use hdphp\services\CacheService;
use Firebase\JWT\JWT;
use think\facade\Env;

/**
 * Jwt
 * Class JwtAuth
 * @package hdphp\utils
 */
class JwtAuth
{
    /**
     * token
     * @var string
     */
    protected $token;

    /**
     * @var string
     */
    protected $app_key = 'hdphp_app_key';

    /**
     * 获取token
     * @param int    $id
     * @param string $type
     * @param array  $params
     * @return array
     */
    public function getToken(int $id, string $type, array $params = []): array
    {
        $host = app()->request->host();
        $time = time();
        $exp_time = strtotime('+ 7day');
        if (app()->request->isApp()) {
            $exp_time = strtotime('+ 30day');
        }
        if ($type == 'out') {
            $exp_time = strtotime('+ 1day');
        }
        $params += [
            'iss' => $host,
            'aud' => $host,
            'iat' => $time,
            'nbf' => $time,
            'exp' => $exp_time,
        ];
        $params['jti'] = compact('id', 'type');
        $token = JWT::encode($params, Env::get('app.app_key', $this->app_key) ?: $this->app_key, 'HS256');

        return compact('token', 'params');
    }

    /**
     * 注释：解析token
     * 创建人：Jack
     * 创建时间：2023/11/22 16:37
     * @param string $jwt
     * @return array
     */
    public function parseToken(string $jwt): array
    {
        $this->token = $jwt;
        [$headb64, $bodyb64, $cryptob64] = explode('.', $this->token);
        $payload = JWT::jsonDecode(JWT::urlsafeB64Decode($bodyb64));
        return [$payload->jti->id, $payload->jti->type, $payload->auth ?? ''];
    }

    /**
     * 注释：验证token
     * 创建人：Jack
     * 创建时间：2023/11/22 17:29
     * @return void
     */
    public function verifyToken()
    {
        JWT::$leeway = 60;
        JWT::decode($this->token, new Key(Env::get('app.app_key', $this->app_key) ?: $this->app_key, 'HS256'));
        $this->token = null;
    }

    /**
     * 获取token并放入令牌桶
     * @param int    $id
     * @param string $type
     * @param array  $params
     * @return array
     */
    public function createToken(int $id, string $type, array $params = [])
    {
        $tokenInfo = $this->getToken($id, $type, $params);
        $exp = $tokenInfo['params']['exp'] - $tokenInfo['params']['iat'] + 60;
        $res = CacheService::setTokenBucket(md5($tokenInfo['token']), ['uid' => $id, 'type' => $type, 'token' => $tokenInfo['token'], 'exp' => $exp], (int)$exp, $type);
        if (!$res) {
            throw new AdminException(100023);
        }
        return $tokenInfo;
    }
}